package com.document.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.document.dto.DatasourceConnection;
import com.document.entity.DocumentTask;
import com.document.entity.schema.Column;
import com.document.entity.schema.DatabaseSchema;
import com.document.entity.schema.Table;
import com.document.mapper.DocumentTaskMapper;
import com.document.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class DocumentTaskService extends ServiceImpl<DocumentTaskMapper, DocumentTask> {

    private final DatabaseMetadataService metadataService;
    private final DocumentGenerator documentGenerator;
    private final UserService userService; // 注入用户服务

    public DocumentTask createTask(DatasourceConnection connection, String sqlContent) {
        DocumentTask task = new DocumentTask();
        task.setTaskId(generateTaskId());
        task.setDbType(connection.getDbType());
        task.setConnectionInfo(encryptConnectionInfo(connection));
        task.setSqlContent(sqlContent);
        task.setStatus("processing");
        task.setTaskName("数据库文档");
        task.setIsPublic(true);

        // 获取当前用户ID
        UserVO currentUser = userService.getCurrentUser();
        task.setUserId(currentUser.getId());

        save(task);
        processTaskAsync(task);

        return task;
    }

    @Async
    public void processTaskAsync(DocumentTask task) {
        log.info("开始处理任务: {}", task.getTaskId());

        try {
            DatabaseSchema schema;

            if (task.getSqlContent() != null && !task.getSqlContent().isEmpty()) {
                log.info("使用SQL文件模式处理任务");
                schema = parseSqlContent(task.getSqlContent());
            } else {
                log.info("使用数据库连接模式处理任务");
                DatasourceConnection connection = decryptConnectionInfo(task.getConnectionInfo());
                schema = metadataService.parseSchema(connection);
            }

            log.info("开始生成HTML文档");
            String htmlContent = documentGenerator.generateHtml(schema);
            task.setResultHtml(htmlContent);
            task.setStatus("success");
            log.info("任务处理成功: {}", task.getTaskId());

        } catch (Exception e) {
            log.error("处理任务失败: {}", task.getTaskId(), e);
            task.setStatus("failed");
            task.setErrorMessage(getErrorMessage(e));
        }

        updateById(task);
    }

    private String getErrorMessage(Exception e) {
        if (e instanceof SQLException) {
            return "数据库连接失败: " + e.getMessage();
        } else if (e instanceof IllegalArgumentException) {
            return "参数错误: " + e.getMessage();
        } else {
            return "文档生成失败: " + e.getMessage();
        }
    }

    private String generateTaskId() {
        return "doc_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    private String encryptConnectionInfo(DatasourceConnection connection) {
        return String.format("{\"host\":\"%s\",\"port\":%d,\"database\":\"%s\",\"username\":\"%s\",\"password\":\"%s\"}",
                connection.getHost(), connection.getPort(), connection.getDatabase(),
                connection.getUsername(), connection.getPassword());
    }

    public DatasourceConnection decryptConnectionInfo(String encryptedInfo) {
        try {
            DatasourceConnection connection = new DatasourceConnection();
            String clean = encryptedInfo.replaceAll("[{}\"]", "");
            String[] pairs = clean.split(",");
            for (String pair : pairs) {
                String[] keyValue = pair.split(":");
                if (keyValue.length == 2) {
                    String key = keyValue[0].trim();
                    String value = keyValue[1].trim();
                    switch (key) {
                        case "host": connection.setHost(value); break;
                        case "port": connection.setPort(Integer.parseInt(value)); break;
                        case "database": connection.setDatabase(value); break;
                        case "username": connection.setUsername(value); break;
                        case "password": connection.setPassword(value); break;
                    }
                }
            }
            connection.setDbType("mysql");
            return connection;
        } catch (Exception e) {
            throw new RuntimeException("解析连接信息失败", e);
        }
    }

    // 简化版本的 SQL 解析方法
    public DatabaseSchema parseSqlContent(String sqlContent) {
        log.info("开始解析SQL文件内容，长度: {} 字符", sqlContent.length());
        DatabaseSchema schema = new DatabaseSchema();
        schema.setDatabaseName("SQL文件导入");

        try {
            // 简单解析：查找 CREATE TABLE 语句
            String[] statements = sqlContent.split(";");

            for (String stmt : statements) {
                String trimmedStmt = stmt.trim();
                if (trimmedStmt.toUpperCase().startsWith("CREATE TABLE")) {
                    processSimpleCreateTable(trimmedStmt, schema);
                }
            }

            log.info("SQL文件解析完成，共找到 {} 张表", schema.getTables().size());

        } catch (Exception e) {
            log.error("处理SQL文件时发生错误", e);
            throw new RuntimeException("处理SQL文件时发生错误: " + e.getMessage());
        }

        return schema;
    }

    private void processSimpleCreateTable(String createTableStmt, DatabaseSchema schema) {
        // 简单解析表名
        String tableName = extractTableName(createTableStmt);
        log.info("解析建表语句: {}", tableName);

        Table table = new Table();
        table.setName(tableName);
        table.setType("TABLE");

        // 简单解析列定义
        extractColumnsSimple(createTableStmt, table);

        schema.getTables().add(table);
    }

    private String extractTableName(String createTableStmt) {
        // 简单提取表名：CREATE TABLE table_name ...
        String[] parts = createTableStmt.split("\\s+");
        for (int i = 0; i < parts.length; i++) {
            if ("TABLE".equalsIgnoreCase(parts[i]) && i + 1 < parts.length) {
                String tableName = parts[i + 1];
                // 去除可能的反引号
                tableName = tableName.replace("`", "");
                return tableName;
            }
        }
        return "unknown_table";
    }

    private void extractColumnsSimple(String createTableStmt, Table table) {
        // 简单提取列定义
        String lowerStmt = createTableStmt.toLowerCase();
        int start = lowerStmt.indexOf("(");
        int end = lowerStmt.lastIndexOf(")");

        if (start > 0 && end > start) {
            String columnSection = createTableStmt.substring(start + 1, end);
            String[] lines = columnSection.split(",");

            for (String line : lines) {
                String trimmed = line.trim();
                if (trimmed.isEmpty()) continue;

                Column column = parseSimpleColumn(trimmed);
                if (column != null) {
                    table.getColumns().add(column);
                }
            }
        }
    }

    private Column parseSimpleColumn(String columnLine) {
        String[] parts = columnLine.split("\\s+");
        if (parts.length < 2) return null;

        Column column = new Column();
        column.setName(parts[0].replace("`", ""));
        column.setType(parts[1].toUpperCase());

        // 简单解析约束
        String lowerLine = columnLine.toLowerCase();
        column.setNullable(!lowerLine.contains("not null"));
        column.setPrimaryKey(lowerLine.contains("primary key"));
        column.setAutoIncrement(lowerLine.contains("auto_increment"));

        // 解析默认值
        if (lowerLine.contains("default")) {
            int defaultIndex = lowerLine.indexOf("default");
            String afterDefault = lowerLine.substring(defaultIndex + 7).trim();
            String[] afterParts = afterDefault.split("\\s+");
            if (afterParts.length > 0) {
                column.setDefaultValue(afterParts[0]);
            }
        }

        return column;
    }

}